package com.liuyucheng.idea_springboot.wechat.mini.controller;

import com.alibaba.fastjson.JSON;
import com.liuyucheng.idea_springboot.bean.Result;
import com.liuyucheng.idea_springboot.wechat.mini.entity.*;
import com.liuyucheng.idea_springboot.wechat.mini.service.WeChatMiniService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.ResourceUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.HandlerMapping;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 微信后端服务控制层
 * @author LiuYuCheng
 */
@Slf4j
@RestController
@RequestMapping("/wechat/mini")
public class WeChatMiniController {

    @Resource
    private WeChatMiniService weChatMiniService;

    @PostMapping("/generateUrlLink")
    public Result<?> generateUrlLink(HttpServletRequest request){
        String url = weChatMiniService.generateUrlLink();
        return Result.data(url);
    }


    /**
     * 通过code换取openId
     * @author LiuYuCheng
     * @param ticketEntity 请求
     * @return 结果
     */
    @PostMapping("/getOpenId")
    public Result<?> getOpenId(@RequestBody TicketEntity ticketEntity){
        String code = ticketEntity.getCode();
        String result = weChatMiniService.getOpenId(code);
        //{"session_key":"MeAuiXMp7NCbJCrwAqCdpg==","openid":"ozpK25UTb0jT4tTYop8kBAomjCAk"}
        MiniUserInfo miniUserInfo = null;
        if(result!=null && !"".equals(result)){
            miniUserInfo = JSON.parseObject(result, MiniUserInfo.class);
        }
        return Result.data(miniUserInfo);
    }

    /**
     * 获取BizToken
     * @author LiuYuCheng
     * @param bizTokenRequest 请求参数
     * @return 结果
     */
    @PostMapping("/getBizToken")
    public Result<?> detectAuth(@RequestBody BizTokenRequest bizTokenRequest){
        BizTokenResponse bizTokenResponse = weChatMiniService.detectAuth(bizTokenRequest);
        return Result.data(bizTokenResponse);
    }

    /**
     * 获取识别结果
     * 如果识别成功,向redis中保存成功的记录,有效期1h,key以openID区分
     * @author LiuYuCheng
     * @param detectInfoRequest 请求参数
     * @return 结果
     */
    @PostMapping("/getDetectInfoEnhanced")
    public Result<?> getDetectInfoEnhanced(@RequestBody DetectInfoRequest detectInfoRequest){
        DetectInfoResponse detectInfoResponse = weChatMiniService.getDetectInfoEnhanced(detectInfoRequest);
        return Result.data(detectInfoResponse);
    }

    /**
     * 获取小程序二维码
     * @author LiuYuCheng
     */
    @GetMapping("/getWxaCodeUnlimited")
    public void getWxaCodeUnlimited(HttpServletResponse response){
        weChatMiniService.getWxaCodeUnlimited(response);
    }

    /**
     * 下载静态资源
     * @author LiuYuCheng
     * @param request 请求
     * @param response 响应
     */
    @GetMapping(value = "/static/**")
    public void view(HttpServletRequest request, HttpServletResponse response) {
        // ISO-8859-1 ==> UTF-8 进行编码转换
        String imgPath = extractPathFromPattern(request);
        if ("".equals(imgPath)) {
            return;
        }
        // 其余处理略
        InputStream inputStream = null;
        OutputStream outputStream = null;
        try {
            imgPath = imgPath.replace("..", "");
            if (imgPath.endsWith(",")) {
                imgPath = imgPath.substring(0, imgPath.length() - 1);
            }
//            File file = ResourceUtils.getFile("classpath:file/test/face.pdf");
            String filePath = "classpath:file/test/" + imgPath;
            log.info("将要下载文件:{}",filePath);
//            File file = FileUtils.getFile(filePath);
            File file = ResourceUtils.getFile(filePath);
            if (!file.exists()) {
                response.setStatus(404);
                throw new RuntimeException("文件不存在..");
            }
            response.setContentType("application/force-download");// 设置强制下载不打开
            String value = "attachment;fileName=" + new String(file.getName().getBytes("UTF-8"), "iso-8859-1");
            value = validateCRLFString(value);
            response.addHeader("Content-Disposition", value);
            inputStream = new BufferedInputStream(FileUtils.openInputStream(ResourceUtils.getFile(filePath)));
            outputStream = response.getOutputStream();
            byte[] buf = new byte[1024];
            int len;
            while ((len = inputStream.read(buf)) > 0) {
                outputStream.write(buf, 0, len);
            }
            response.flushBuffer();
        } catch (IOException e) {
            response.setStatus(404);
            log.error("预览文件失败:{}" , e.getMessage());
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
					log.error(e.getMessage(), e);
                }
            }
            if (outputStream != null) {
                try {
                    outputStream.close();
                } catch (IOException e) {
					log.error(e.getMessage(), e);
                }
            }
        }
    }

    private static String extractPathFromPattern(final HttpServletRequest request) {
        String path = (String) request.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE);
        String bestMatchPattern = (String) request.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE);
        return new AntPathMatcher().extractPathWithinPattern(bestMatchPattern, path);
    }

    /**
     * 去除字符串中的换行符,防止出现HTTP响应拆分漏洞
     * @param value value
     * @return value
     */
    public static String validateCRLFString(String value) {
        String regex = "[\\r,\\n]";
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(value);
        value = matcher.replaceAll("").trim();
        return value;
    }

    public static void main(String[] args) throws FileNotFoundException {
        File file = ResourceUtils.getFile("classpath:file/test/face.pdf");
        System.out.println("file.exists() = " + file.exists());
    }
}
